package za.ac.sun.cs.viz.distrib;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

@SuppressWarnings("serial")
public class Viz extends JFrame implements ChangeListener {

	private final static String DEFAULT_FILENAME = "test-input3.txt";

	private JPanel mainPanel;
	private JPanel bottomBar;
	private JButton leftButton;
	private JButton rightButton;
	private JLabel timestampLabel;
	private JSlider timeSlider;
	private JScrollPane treeScrollPane;
	private VizTreePane treePane;
	private VizTreeManager treeManager;

	public Viz(String filename) {
		treeManager = new VizTreeManager(filename);
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		initializeDesktop();
		initializePlacement();
	}

	private void initializeDesktop() {
		int n = treeManager.getTimestampCount();
		leftButton = new JButton(goLeftAction);
		rightButton = new JButton(goRightAction);
		timeSlider = new JSlider(0, n - 1, 0);
		timeSlider.addChangeListener(this);
		if (n < 50) {
			timeSlider.setMajorTickSpacing(1);
		} else if (n < 500) {
			timeSlider.setMajorTickSpacing(10);
		} else if (n < 5000) {
			timeSlider.setMajorTickSpacing(100);
		} else if (n < 50000) {
			timeSlider.setMajorTickSpacing(1000);
		} else {
			timeSlider.setMajorTickSpacing((n + 49) / 50);
		}
		timeSlider.setPaintTicks(true);
		timestampLabel = new JLabel();
		timestampLabel.setVisible(false);
		bottomBar = new JPanel(new BorderLayout());
		bottomBar.add(leftButton, BorderLayout.WEST);
		bottomBar.add(rightButton, BorderLayout.EAST);
		bottomBar.add(timeSlider, BorderLayout.CENTER);
		bottomBar.add(timestampLabel, BorderLayout.NORTH);

		treePane = new VizTreePane(treeManager.getTree(0));
		treeScrollPane = new JScrollPane(treePane);

		mainPanel = new JPanel(new BorderLayout());
		mainPanel.add(bottomBar, BorderLayout.SOUTH);
		mainPanel.add(treeScrollPane, BorderLayout.CENTER);
		mainPanel.getInputMap().put(KeyStroke.getKeyStroke("RIGHT"), "goRight");
		mainPanel.getActionMap().put("goRight", goRightAction);
		mainPanel.getInputMap().put(KeyStroke.getKeyStroke("LEFT"), "goLeft");
		mainPanel.getActionMap().put("goLeft", goLeftAction);
		mainPanel.getInputMap().put(KeyStroke.getKeyStroke("typed l"), "toggleLabel");
		mainPanel.getActionMap().put("toggleLabel", toggleLabelAction);

		setContentPane(mainPanel);
	}

	private void initializePlacement() {
		pack();
		final Dimension s = Toolkit.getDefaultToolkit().getScreenSize();
		final int i = 50;
		final int w = s.width - i * 2;
		final int h = s.height - i * 2;
		setBounds(i, i, w, h);
		setLocationRelativeTo(null);
	}

	public static void main(final String args[]) {
		String filename = DEFAULT_FILENAME;
		if (args.length > 0) {
			filename = args[0];
		}
		final Viz viz = new Viz(filename);
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				viz.setVisible(true);
			}
		});
	}

	@Override
	public void stateChanged(ChangeEvent e) {
		JSlider source = (JSlider) e.getSource();
		if (!source.getValueIsAdjusting()) {
			int time = (int) source.getValue();
			treePane.update(treeManager.getTree(time));
			timestampLabel.setText(treeManager.getText(time));
		}
	}

	private Action goLeftAction = new AbstractAction("<") {
		@Override
		public void actionPerformed(ActionEvent e) {
			timeSlider.setValue(timeSlider.getValue() - 1);
		}
	};

	private Action goRightAction = new AbstractAction(">") {
		@Override
		public void actionPerformed(ActionEvent e) {
			timeSlider.setValue(timeSlider.getValue() + 1);
		}
	};

	private Action toggleLabelAction = new AbstractAction("toggleLabel") {
		@Override
		public void actionPerformed(ActionEvent e) {
			timestampLabel.setVisible(!timestampLabel.isVisible());
		}
	};
	
}
